package com.fg.pro.trade.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.shaded.javax.annotation.meta.When;
import com.fg.pro.model.trade.dto.*;
import com.fg.pro.trade.dao.TradeGoodsDao;
import com.fg.pro.trade.dao.TradeGoodsSimulationDao;
import com.fg.pro.trade.entity.TradeSale;
import com.fg.pro.trade.service.TradeGoodsSimulationService;
import com.fg.pro.trade.service.TradeSaleService;
import com.fg.pro.trade.utils.TradeGoodsSimulationUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.fg.pro.trade.utils.TradeComputerUtils.*;

@Service(value = "tradeGoodsSimulationService")
public class TradeGoodsSimulationServiceImpl implements TradeGoodsSimulationService {

    @Autowired
    TradeGoodsSimulationDao tradeGoodsSimulationDao;
    @Autowired
    TradeGoodsSimulationUtils tradeGoodsSimulationUtils;
    @Resource
    private TradeSaleService tradeSaleService;

    @Override
    public SimulationDataDto getCategoryFirByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("一级分类");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            List<SimulationCateGoryDto> list = tradeGoodsSimulationDao.getCategoryFirByParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(list);
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }
        // 计算总销售额
//        double sumSalePrice = simulationSaleList.stream()
//                .filter(tradeSale -> tradeSale.getSaleGoodsRealDealPrice() != null)
//                .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
//                .sum();

        // 分组并转换
        List<SimulationCateGoryDto> simulationDataList = simulationSaleList.stream()
                .filter(tradeSale -> tradeSale.getSaleCategoryFirId() != null)
                .collect(Collectors.groupingBy(
                        TradeSale::getSaleCategoryFirId,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    // 获取分类名称
                                    String categoryName = list.stream()
                                            .filter(ts -> ts.getSaleCategoryFirName() != null)
                                            .findFirst()
                                            .map(TradeSale::getSaleCategoryFirName)
                                            .orElse("未知分类");

                                    //  计算分类销成本
                                    double costPrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                            .sum();
                                    // 计算分类销售额
                                    double salePrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                            .sum();

                                    // 计算销售额占比
                                    SimulationCateGoryDto dto = new SimulationCateGoryDto();
                                    dto.setCategoryId(list.get(0).getSaleCategoryFirId());
                                    dto.setCategoryName(categoryName);
                                    dto.setSalePrice(salePrice);
//                                    dto.setSalePriceRate(getSalePriceRate(salePrice,sumSalePrice));
                                    dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                    dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                    return dto;
                                }
                        )
                ))
                .values().stream()
                .collect(Collectors.toList());

        result.setData(simulationDataList);
        return result;
    }


    @Override
    public SimulationDataDto getCategorySecByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("二级分类");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            List<SimulationCateGoryDto> list = tradeGoodsSimulationDao.getCategorySecByParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(list);
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }
        // 计算总销售额
//        double sumSalePrice = simulationSaleList.stream()
//                .filter(tradeSale -> tradeSale.getSaleGoodsRealDealPrice() != null)
//                .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
//                .sum();

        // 分组并转换
        List<SimulationCateGoryDto> simulationDataList = simulationSaleList.stream()
                .filter(tradeSale -> tradeSale.getSaleCategorySecId() != null)
                .collect(Collectors.groupingBy(
                        TradeSale::getSaleCategorySecId,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    // 获取分类名称
                                    String categoryName = list.stream()
                                            .filter(ts -> ts.getSaleCategorySecName() != null)
                                            .findFirst()
                                            .map(TradeSale::getSaleCategoryFirName)
                                            .orElse("未知分类");

                                    //  计算分类销成本
                                    double costPrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                            .sum();
                                    // 计算分类销售额
                                    double salePrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                            .sum();

                                    // 计算销售额占比
                                    SimulationCateGoryDto dto = new SimulationCateGoryDto();
                                    dto.setCategoryId(list.get(0).getSaleCategorySecId());
                                    dto.setCategoryName(categoryName);
                                    dto.setSalePrice(salePrice);
//                                    dto.setSalePriceRate(getSalePriceRate(salePrice,sumSalePrice));
                                    dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                    dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                    return dto;
                                }
                        )
                ))
                .values().stream()
                .collect(Collectors.toList());

        result.setData(simulationDataList);
        return result;
    }

    @Override
    public SimulationDataDto getCategoryListByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText(categorySecId == null ? "一级分类" : "二级分类");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            if (categorySecId == null) {
                List<SimulationCateGoryDto> list = tradeGoodsSimulationDao.getCategoryListByFirParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
                result.setData(list);
            } else {
                List<SimulationCateGoryDto> list = tradeGoodsSimulationDao.getCategoryListBySecParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
                result.setData(list);
            }
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }

        // 分组并转换
        List<SimulationCateGoryDto> simulationDataList = new ArrayList<>();
        if (categorySecId == null) {
            simulationDataList = simulationSaleList.stream()
                    .filter(tradeSale -> tradeSale.getSaleCategoryFirId() != null)
                    .collect(Collectors.groupingBy(
                            TradeSale::getSaleCategoryFirId,
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    list -> {
                                        // 获取分类名称
                                        String categoryName = list.stream()
                                                .filter(ts -> ts.getSaleCategoryFirId() != null)
                                                .findFirst()
                                                .map(TradeSale::getSaleCategoryFirName)
                                                .orElse("未知分类");

                                        //  计算分类销成本
                                        double costPrice = list.stream()
                                                .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                                .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                                .sum();
                                        // 计算分类销售额
                                        double salePrice = list.stream()
                                                .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                                .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                                .sum();

                                        // 计算销售额占比
                                        SimulationCateGoryDto dto = new SimulationCateGoryDto();
                                        dto.setCategoryId(list.get(0).getSaleCategorySecId());
                                        dto.setCategoryName(categoryName);
                                        dto.setSalePrice(salePrice);
//                                    dto.setSalePriceRate(getSalePriceRate(salePrice,sumSalePrice));
                                        dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                        dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                        return dto;
                                    }
                            )
                    ))
                    .values().stream()
                    .sorted((dto1, dto2) -> Double.compare(dto2.getSalePrice(), dto1.getSalePrice()))
                    .collect(Collectors.toList());
        } else {
            simulationDataList = simulationSaleList.stream()
                    .filter(tradeSale -> tradeSale.getSaleCategorySecId() != null)
                    .collect(Collectors.groupingBy(
                            TradeSale::getSaleCategorySecId,
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    list -> {
                                        // 获取分类名称
                                        String categoryName = list.stream()
                                                .filter(ts -> ts.getSaleCategorySecName() != null)
                                                .findFirst()
                                                .map(TradeSale::getSaleCategorySecName)
                                                .orElse("未知分类");

                                        //  计算分类销成本
                                        double costPrice = list.stream()
                                                .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                                .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                                .sum();
                                        // 计算分类销售额
                                        double salePrice = list.stream()
                                                .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                                .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                                .sum();

                                        // 计算销售额占比
                                        SimulationCateGoryDto dto = new SimulationCateGoryDto();
                                        dto.setCategoryId(list.get(0).getSaleCategorySecId());
                                        dto.setCategoryName(categoryName);
                                        dto.setSalePrice(salePrice);
//                                    dto.setSalePriceRate(getSalePriceRate(salePrice,sumSalePrice));
                                        dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                        dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                        return dto;
                                    }
                            )
                    ))
                    .values().stream()
                    .sorted((dto1, dto2) -> Double.compare(dto2.getSalePrice(), dto1.getSalePrice()))
                    .collect(Collectors.toList());
        }


        result.setData(simulationDataList);
        return result;
    }


    @Override
    public SimulationDataDto getCustomerDataBySaleType(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("客户属性");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            List<SimulationTypeDto> list = tradeGoodsSimulationDao.getCustomerDataBySaleType(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(list);
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }
        // 计算总销售额
//        double sumSalePrice = simulationSaleList.stream()
//                .filter(tradeSale -> tradeSale.getSaleGoodsRealDealPrice() != null)
//                .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
//                .sum();

        // 分组并转换
        List<SimulationTypeDto> simulationDataList = simulationSaleList.stream()
                .filter(tradeSale -> tradeSale.getCustomerId() != null)
                .collect(Collectors.groupingBy(
                        TradeSale::getCustomerExportType,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
//                                    typeStr
                                    String typeStr = list.stream()
                                            .filter(ts -> ts.getCustomerExportType() != null)
                                            .findFirst()
                                            .map(item -> {
                                                String str = "客户属性";
                                                switch (item.getCustomerExportType()) {
                                                    case 1:
                                                        str = "对内";
                                                        break;
                                                    case 2:
                                                        str = "对外";
                                                        break;
                                                    case 3:
                                                        str = "监狱";
                                                        break;
                                                    case 4:
                                                        str = "新添加";
                                                        break;
                                                }
                                                return str;
                                            })
                                            .orElse("未知客户类型");
//                                    typeValue
                                    Integer typeValue = list.stream()
                                            .filter(ts -> ts.getCustomerExportType() != null)
                                            .findFirst()
                                            .map(TradeSale::getCustomerExportType)
                                            .orElse(0);


                                    //  计算分类销成本
                                    double costPrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                            .sum();
                                    // 计算分类销售额
                                    double salePrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                            .sum();

                                    // 计算销售额占比
                                    SimulationTypeDto dto = new SimulationTypeDto();
                                    dto.setTypeStr(typeStr);
                                    dto.setTypeValue(typeValue);
                                    dto.setSalePrice(salePrice);
                                    dto.setCostPrice(costPrice);
                                    dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                    dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                    return dto;
                                }
                        )
                ))
                .values().stream()
                .sorted((dto1, dto2) -> Double.compare(dto2.getSalePrice(), dto1.getSalePrice()))
                .collect(Collectors.toList());

        result.setData(simulationDataList);
        return result;
    }

    @Override
    public SimulationDataDto getCustomerListByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("客户列表");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            List<SimulationCustomerDto> list = tradeGoodsSimulationDao.getCustomerListByParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(list);
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }
        // 计算总销售额
//        double sumSalePrice = simulationSaleList.stream()
//                .filter(tradeSale -> tradeSale.getSaleGoodsRealDealPrice() != null)
//                .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
//                .sum();

        // 分组并转换
        List<SimulationCustomerDto> simulationDataList = simulationSaleList.stream()
                .filter(tradeSale -> tradeSale.getCustomerId() != null)
                .collect(Collectors.groupingBy(
                        TradeSale::getCustomerLine,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    //              customerLine
                                    String newCustomerLine = list.stream()
                                            .filter(ts -> ts.getSaleCustomerLine() != null)
                                            .findFirst()
                                            .map(TradeSale::getCustomerLine)
                                            .orElse("aa");

                                    //  计算分类销成本
                                    double costPrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                            .sum();
                                    // 计算分类销售额
                                    double salePrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                            .sum();

                                    // 计算销售额占比
                                    SimulationCustomerDto dto = new SimulationCustomerDto();
                                    dto.setCustomerLine(newCustomerLine);
                                    dto.setSalePrice(salePrice);
                                    dto.setCostPrice(costPrice);
                                    dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                    dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                    return dto;
                                }
                        )
                ))
                .values().stream()
                .sorted((dto1, dto2) -> Double.compare(dto2.getSalePrice(), dto1.getSalePrice()))
                .collect(Collectors.toList());

        result.setData(simulationDataList);
        return result;
    }

    @Override
    public SimulationDataDto getGoodsListByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("商品列表");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            List<SimulationGoodsDto> list = tradeGoodsSimulationDao.getGoodsListByParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(list);
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }

        // 分组并转换
        List<SimulationGoodsDto> simulationDataList = simulationSaleList.stream()
                .filter(tradeSale -> tradeSale.getGoodsId() != null)
                .collect(Collectors.groupingBy(
                        TradeSale::getGoodsId,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    //              goodsId

                                    Long newGoodsId = list.stream()
                                            .filter(ts -> ts.getGoodsId() != null)
                                            .findFirst()
                                            .map(TradeSale::getGoodsId)
                                            .orElse(0L);
                                    //              goodsName
                                    String newGoodsName = list.stream()
                                            .filter(ts -> ts.getSaleGoodsName() != null)
                                            .findFirst()
                                            .map(TradeSale::getSaleGoodsName)
                                            .orElse("商品名称异常");
                                    // saleNum
                                    double saleNum = list.stream()
                                            .filter(ts -> ts.getSaleGoodsBaseOutstock() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsBaseOutstock)
                                            .sum();
                                    //  计算分类销成本
                                    double costPrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice)
                                            .sum();
                                    // 计算分类销售额
                                    double salePrice = list.stream()
                                            .filter(ts -> ts.getSaleGoodsRealDealPrice() != null)
                                            .mapToDouble(TradeSale::getSaleGoodsRealDealPrice)
                                            .sum();

                                    // 计算销售额占比
                                    SimulationGoodsDto dto = new SimulationGoodsDto();
                                    dto.setGoodsId(newGoodsId);
                                    dto.setGoodsName(newGoodsName);
                                    dto.setSalePrice(salePrice);
                                    dto.setCostPrice(costPrice);
                                    dto.setGrossPrice(getGrossPrice(salePrice, costPrice));
                                    dto.setGrossMargin(getGrossMargin(salePrice, costPrice));
                                    dto.setUnitSalePrice(getUnitSalePrice(salePrice, saleNum));
                                    dto.setUnitCostPrice(getUnitSalePrice(costPrice, saleNum));
                                    return dto;
                                }
                        )
                ))
                .values().stream()
                .sorted((dto1, dto2) -> Double.compare(dto2.getSalePrice(), dto1.getSalePrice()))
                .collect(Collectors.toList());

        result.setData(simulationDataList);
        return result;
    }

    @Override
    public SimulationDataDto getOrderDetailByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("订单详情");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            List<SimulationOrderDetailDto> list = tradeGoodsSimulationDao.getOrderDetailByParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(list);
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }

        // 分组并转换
        List<SimulationOrderDetailDto> simulationDataList = simulationSaleList.stream().map(item -> {
                    SimulationOrderDetailDto dto = new SimulationOrderDetailDto();
                    dto.setGoodsId(item.getGoodsId());
                    dto.setGoodsName(item.getSaleGoodsName());
//                    dto.setUnitStr(item.getSaleGoodsOrderUnit());
                    dto.setUnitStr(item.getSaleGoodsBaseUnit());
//                    dto.setSaleNum(item.getSaleGoodsBaseOutstock());
                    dto.setSaleNum(item.getSaleGoodsBaseOutstock());
                    dto.setSalePrice(item.getSaleGoodsRealDealPrice());
                    dto.setCostPrice(item.getSaleGoodsOutstockCostPrice());
//                    dto.setUnitPrice(item.getSaleGoodsOrderUnitPrice());
                    dto.setUnitPrice(item.getSaleGoodsBasePrice());
                    dto.setUnitCostPrice(getUnitSalePrice(item.getSaleGoodsOutstockCostPrice(),item.getSaleGoodsBaseOutstock()));
                    dto.setGrossMargin(getGrossMargin(item.getSaleGoodsRealDealPrice(), item.getSaleGoodsOutstockCostPrice()));
//                    dto.setGrossPrice(item.getSaleGoodsOutstockCostPrice());
                    dto.setGrossPrice(getGrossPrice(item.getSaleGoodsRealDealPrice(), item.getSaleGoodsOutstockCostPrice()));
                    dto.setCreateTime(item.getCreateTime());
                    return dto;
                })
                .sorted((dto1, dto2) -> Double.compare(dto2.getSalePrice(), dto1.getSalePrice()))
                .collect(Collectors.toList());


        result.setData(simulationDataList);
        return result;
    }

    @Override
    public SimulationDataDto getTitileByParams(Date start, Date end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 规则
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        // 返回数据
        SimulationDataDto result = new SimulationDataDto();
        result.setText("标题");
        result.setFlag(simulationGoodsList == null ? false : simulationGoodsList.isEmpty());
        result.setSubtext(simulationGoodsList == null ? "" : simulationGoodsList.isEmpty() ? "" : "存在虚拟数据");
        // 真实数据直接返回
        if (simulationGoodsList == null || simulationGoodsList.isEmpty()) {
            SimulationStrDto data = tradeGoodsSimulationDao.getTitileByParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);
            result.setData(List.of(data));
            return result;
        }
        // 模拟数据加工后返回
        List<TradeSale> simulationSaleList = getResultGoodsBySimulationParams(sdf.format(DateUtil.beginOfDay(start)), sdf.format(DateUtil.endOfDay(end)), categoryFirId, categorySecId, saleType, customerId, goodsId, simulationGoodsList, customerLine);
        if (simulationSaleList.isEmpty()) {
            result.setData(new ArrayList());
            return result;
        }

        // 分组并转换
        SimulationStrDto simulationStrDto = new SimulationStrDto();
        double sumSalePrice = simulationSaleList.stream().filter(ts -> ts.getSaleGoodsRealDealPrice() != null).mapToDouble(TradeSale::getSaleGoodsRealDealPrice).sum();
        double sumCostPrice = simulationSaleList.stream().filter(ts -> ts.getSaleGoodsOutstockCostPrice() != null).mapToDouble(TradeSale::getSaleGoodsOutstockCostPrice).sum();
        simulationStrDto.setCostPrice(sumCostPrice);
        simulationStrDto.setSalePrice(sumSalePrice);
        simulationStrDto.setGrossPrice(getGrossPrice(sumSalePrice, sumCostPrice));
        simulationStrDto.setGrossMargin(getGrossMargin(sumSalePrice, sumCostPrice));
        result.setData(List.of(simulationStrDto));
        return result;
    }

    private List<TradeSale> getResultGoodsBySimulationParams(String start, String end, Long categoryFirId, Long categorySecId, Long saleType, Long customerId, Long goodsId, List<SimulationGoodsParamsDto> simulationGoodsList, String customerLine) {
        List<String> allowCustomerLine = tradeGoodsSimulationUtils.getAllowCustomerLine();
        List<TradeSale> realList = tradeGoodsSimulationDao.getGoodsBySimulationParams(start, end, categoryFirId, categorySecId, saleType, customerId, goodsId, allowCustomerLine, customerLine);

        Map<String, SimulationGoodsParamsDto> map = simulationGoodsList.stream().collect(Collectors.toMap(
                dto -> dto.getCustomerLine() + "-" + dto.getGoodsId(),
                dto -> dto,
                (v1, v2) -> v2
        ));

        for (TradeSale tradeSale : realList) {
            if (map.containsKey(tradeSale.getCustomerLine() + "-" + tradeSale.getGoodsId())) {
                SimulationGoodsParamsDto simulationGoodsParamsDto = map.get(tradeSale.getCustomerLine() + "-" + tradeSale.getGoodsId());
//                getSaleGoodsSaleOutstockPrice 计算分类销成本
//                getSaleGoodsRealDealPrice 计算分类销售额
                tradeSale.setSaleGoodsBasePrice(simulationGoodsParamsDto.getUnitSalePrice());
                tradeSale.setSaleGoodsRealDealPrice(NumberUtil.mul(tradeSale.getSaleGoodsBaseOutstock(), simulationGoodsParamsDto.getUnitSalePrice()));
                tradeSale.setSaleGoodsOutstockCostPrice(NumberUtil.mul(tradeSale.getSaleGoodsBaseOutstock(), simulationGoodsParamsDto.getUnitCostPrice()));
            }
        }
        return realList;
    }


}
